/* QtLua -- Lua bindings for Qt
   Copyright (C) 2011, Jarek Pelczar

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General
   Public License along with this library; if not, write to the
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301 USA

*/

#include "qdatetime_prototype.h"
#include "qluascriptvalue.h"
#include "qluascriptcontext.h"
#include "qluaexception.h"
#include <QDebug>

QDateTime_prototype::QDateTime_prototype(QObject *parent) :
    QObject(parent)
{
}

QDateTime * QDateTime_prototype::ptr() const
{
    QDateTime * ptr = qtlua_scriptvalue_cast<QDateTime>(thisObject());
    if(!ptr) {
        engine()->throwException(engine()->newException(QLatin1String("QDateTime_prototype: Unable to cast this object to QDateTime")));
    }
    return ptr;
}

bool QDateTime_prototype::isNull() const
{
    QDateTime * self = ptr();
    return self ? self->isNull() : true;
}

bool QDateTime_prototype::isValid() const
{
    QDateTime * self = ptr();
    return self ? self->isValid() : false;
}

QString QDateTime_prototype::toString() const
{
    QDateTime * self = ptr();
    return self ? self->toString() : QString();
}

QDateTime QDateTime_prototype::addDays(int ndays) const
{
    QDateTime * self = ptr();
    return self ? self->addDays(ndays) : QDateTime();
}

QDateTime QDateTime_prototype::addMSecs(qint64 msecs) const
{
    QDateTime * self = ptr();
    return self ? self->addMSecs(msecs) : QDateTime();
}

QDateTime QDateTime_prototype::addMonths(int nmonths) const
{
    QDateTime * self = ptr();
    return self ? self->addMonths(nmonths) : QDateTime();
}

QDateTime QDateTime_prototype::addSecs(int s) const
{
    QDateTime * self = ptr();
    return self ? self->addSecs(s) : QDateTime();
}

QDateTime QDateTime_prototype::addYears(int nyears) const
{
    QDateTime * self = ptr();
    return self ? self->addYears(nyears) : QDateTime();
}

int QDateTime_prototype::daysTo(const QDateTime & dt) const
{
    return ptr()->daysTo(dt);
}

int QDateTime_prototype::secsTo(const QDateTime & dt) const
{
    return ptr()->secsTo(dt);
}

qint64 QDateTime_prototype::msecsTo(const QDateTime & dt) const
{
    return ptr()->msecsTo(dt);
}

qint64 QDateTime_prototype::toMSecsSinceEpoch() const
{
    return ptr()->toMSecsSinceEpoch();
}

QDateTime_wrapper::QDateTime_wrapper(QLuaScriptEngine * engine)
    : QObject(engine),
      QLuaScriptClass(engine)
{
    m_proto = engine->newQObject(new QDateTime_prototype(engine),
                                 QLuaScriptEngine::ScriptOwnership);

    engine->setGlobal("QDateTime", engine->newQObject(this));
    engine->setGlobal("QDateTime_prototype", m_proto);

    qluaRegisterScriptMetaType<QDateTime>(engine,
                                          QDateTime_toScriptValue,
                                          QDateTime_fromScriptValue);
}

QDateTime_wrapper::QueryFlags QDateTime_wrapper::queryProperty(const QLuaScriptValue& object,
                                 const QByteArray& name)
{
    if(name == "newDateTime") {
        return HandlesCallAccess;
    }

    if(name == "currentDateTime") {
        return HandlesCallAccess;
    }

    if(name == "currentDateTimeUtc") {
        return HandlesCallAccess;
    }

    return 0;
}

QLuaScriptValue QDateTime_wrapper::property(const QLuaScriptValue& object,
                                      const QByteArray& name)
{
    if(name == "newDateTime") {
        return scriptEngine()->newFunction(new_obj);
    }

    if(name == "currentDateTime") {
        return scriptEngine()->newFunction(new_current);
    }

    if(name == "currentDateTimeUtc") {
        return scriptEngine()->newFunction(new_currentUtc);
    }

    return QLuaScriptValue();
}

void QDateTime_wrapper::setProperty(const QLuaScriptValue& object,
                         const QByteArray& name,
                         const QLuaScriptValue& value)
{

}

QLuaScriptValue QDateTime_wrapper::prototype() const
{
    return m_proto;
}

QString QDateTime_wrapper::name() const
{
    return "QDateTime";
}

QLuaScriptValue QDateTime_wrapper::new_obj(QLuaScriptContext * context, QLuaScriptEngine * engine)
{
    QLuaScriptValue value = engine->newUserDataWithGc<QDateTime>(engine->getGlobal("QDateTime_prototype"));

    QDateTime * obj = qtlua_scriptvalue_cast<QDateTime>(value);

    return value;
}

QLuaScriptValue QDateTime_wrapper::new_current(QLuaScriptContext *, QLuaScriptEngine * engine)
{
    QLuaScriptValue value = engine->newUserDataWithGc<QDateTime>(engine->getGlobal("QDateTime_prototype"));

    QDateTime * obj = qtlua_scriptvalue_cast<QDateTime>(value);

    *obj = QDateTime::currentDateTime();

    return value;
}

QLuaScriptValue QDateTime_wrapper::new_currentUtc(QLuaScriptContext *, QLuaScriptEngine * engine)
{
    QLuaScriptValue value = engine->newUserDataWithGc<QDateTime>(engine->getGlobal("QDateTime_prototype"));

    QDateTime * obj = qtlua_scriptvalue_cast<QDateTime>(value);

    *obj = QDateTime::currentDateTimeUtc();

    return value;
}

QLuaScriptValue QDateTime_wrapper::QDateTime_toScriptValue(QLuaScriptEngine * engine, const QDateTime * t)
{
    QLuaScriptValue value = engine->newUserDataWithGc<QDateTime>(engine->getGlobal("QDateTime_prototype"));
#ifdef QT_DEBUG
    qDebug() << "[QtLua] Convert QDateTime to QLuaScriptValue";
#endif
    QDateTime * obj = qtlua_scriptvalue_cast<QDateTime>(value);
    if(t)
        *obj = *t;
    return value;
}

void QDateTime_wrapper::QDateTime_fromScriptValue(const QLuaScriptValue& value, QDateTime * t)
{
#ifdef QT_DEBUG
    qDebug() << "[QtLua] Convert QLuaScriptValue to QDateTime";
#endif

    if(value.isString()) {
        *t = QDateTime::fromString(value.toUnicode(), Qt::ISODate);
    } else if(value.isUserData()) {
        QDateTime * scriptT = qtlua_scriptvalue_cast<QDateTime>(value);
        if(scriptT) {
            *t = *scriptT;
        } else {
            qWarning("[QtLua] Trying to convert from another metatype of userdata to QDateTime");
        }
    } else {
        qWarning("[QtLua] No conversion to QDateTime");
    }
}
